/**
 * 线程同步机制包装类
 * 分别对 信号量，互斥锁，条件变量 进行封装
 * @author: sundx
 * @date: 2020-06-06 22:13:44
 * @Last Modified by: sundx
 * @Last Modified time: 2020-06-07 00:29:37
 */
#ifndef __LOCKER_H__
#define __LOCKER_H__

#include "../utilities/utilities.h"
#include <cerrno>
#include <pthread.h>
#include <semaphore.h>

// 对信号量的封装
class sem {
public:
  sem() { // 构造函数内暂时设置信号量为线程同步使用，进程不共享
    if (sem_init(&m_sem, PTHREAD_PROCESS_PRIVATE, 0) == -1)
      printError("sem() error...");
  }
  sem(int num) { // 设置为num；
    if (sem_init(&m_sem, PTHREAD_PROCESS_PRIVATE, num) == -1)
      printError("sem(num) error...");
  }
  ~sem() {
    if (sem_destroy(&m_sem) == -1)
      printError("sem_destory() error...");
  }
  bool wait() { // 等待信号量
    return sem_wait(&m_sem) == 0;
  }
  bool post() { // 增加信号量
    return sem_post(&m_sem) == 0;
  }

private:
  sem_t m_sem;
};

// 对互斥锁的封装
class mutexLock {
public:
  mutexLock() { //初始化锁
    if (pthread_mutex_init(&m_mutex, nullptr) != 0)
      printError("pthread_mutex_init() error...");
  }
  ~mutexLock() { //释放锁
    if (pthread_mutex_destroy(&m_mutex) != 0)
      printError("pthread_mutex_destroy() error...");
  }
  bool lock() { return pthread_mutex_lock(&m_mutex) == 0; }     //加锁
  bool unlock() { return pthread_mutex_unlock(&m_mutex) == 0; } //解锁

public:
  pthread_mutex_t m_mutex;
};

// 对条件变量的封装
class cond {
public:
  cond() { //对锁和条件变量初始化  自动初始化子对象；
    if (pthread_cond_init(&m_cond, nullptr) != 0) {
      printError("pthread_mutex_init() error...");
    }
    std::cout << "cond init" << std::endl;
  }
  ~cond() { //析构，释放锁和条件变量
    pthread_cond_destroy(&m_cond);
    std::cout << "cond release" << std::endl;
  }
  bool wait() { // 阻塞等待条件变量
    condMutex.lock();
    int ret = pthread_cond_wait(&m_cond, &(condMutex.m_mutex));
    condMutex.unlock();
    return ret == 0;
  }
  bool waitTime(timespec *t) { //超时等待；
    condMutex.lock();
    int ret = pthread_cond_timedwait(&m_cond, &(condMutex.m_mutex), t);
    condMutex.unlock();
    return ret == 0;
  }
  bool signal() { return pthread_cond_signal(&m_cond) == 0; } //通知一个左右
  bool broadcast() { return pthread_cond_broadcast(&m_cond) == 0; } //全都通知；

private:
  mutexLock condMutex;
  pthread_cond_t m_cond;
};

#endif